package com.cskaoyan.javase.oop3._0abstract._0introduction;

import javafx.animation.Animation;

import java.util.AbstractCollection;

/**
 * 思考一下Animal类的继承体系，有什么问题吗？
 *
 * 从以下两个角度分析：
 *      1.从代码角度上，有没有冗余代码？
 *      2.从设计角度上，在这个案例中，会存在一个动物对象吗？
 *
 * 综上，我们提出两个改进的方向：
 *      1.Animal类就是作为顶层抽象祖先类而存在的，不需要创建对象，于是干脆不要创建对象了。
 *      2.Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。
 *
 * 在正常Java代码中,一个方法,要么有方法体是一个带有实现的具体方法
 * 要么就必须声明为abstract,就必须声明为抽象方法
 *
 * 如何声明抽象方法呢?
 * 语法:
 * [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 *
 * 普通类当中是不允许存在抽象方法的,如果想要有抽象方法,那么该类就必须定义为抽象类
 * 如何定义抽象类呢?
 * 语法:
 * [访问权限修饰符] abstract 类名{
 *     // 抽象类的类体
 * }
 *
 * 补充,扩展:
 *      1.抽象类是抽象的,它不能被实例化,不能new对象
 *      2.抽象类中抽象方法和具体子类中的具体方法实现,它们之间也是方法的重写关系,符合方法重写的语法
 *      3.抽象类也是类,它也能被继承,它和子类之间的关系仍然是"is-a"的关系,仍然存在多态现象
 *
 * @since 15:44
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstract; cannot be instantiated
        // new Animal();

        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}

// Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
abstract class Animal {
    // '{' or ';' expected
    // Missing method body, or declare abstract
    // Abstract method in non-abstract class
    public abstract void shout();
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}